/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package dnstry;

import java.util.ArrayList;

/**
 *
 * @author Claudiu
 */
public class DnsAnswer {

    private byte[] dnsAnswer;
    private byte[] dnsFullResponse;
    private int answerRecordCount;
    private int nameServerCount;
    private int additionRecordsCount;
    private int ttl;
    private int type;
    private int rLength;
    private int offset;
    private ArrayList<String> answers;
    public ArrayList<DnsEntry> entryList;

    public DnsAnswer() {
    }

    public DnsAnswer(byte[] _dnsFullResponse, int _questionMessageSize) {

        dnsAnswer = new byte[_dnsFullResponse.length];
        dnsFullResponse = _dnsFullResponse;
        // dnsAnswer= _dnsAnswer;
        offset =_questionMessageSize-1;
        for (int i = _questionMessageSize + 1; i < _dnsFullResponse.length; i++) {
            dnsAnswer[i - _questionMessageSize] = (byte) (_dnsFullResponse[i] & 0x7f);
        }
        answerRecordCount = 256 * dnsFullResponse[6] + dnsFullResponse[7];
        nameServerCount = 256 * dnsFullResponse[8] + dnsFullResponse[9];
        additionRecordsCount = 256 * dnsFullResponse[10] + dnsFullResponse[11];

    }

    public void getAnswerFromWholeMessage(byte[] _dnsResponse, int _questionMessageSize) {
        for (int i = _questionMessageSize; i < _dnsResponse.length; i++) {
            dnsAnswer[i - _questionMessageSize] = _dnsResponse[i];
        }
        answerRecordCount = 256 * dnsFullResponse[6] + dnsFullResponse[7];
        nameServerCount = 256 * dnsFullResponse[8] + dnsFullResponse[9];
        additionRecordsCount = 256 * dnsFullResponse[10] + dnsFullResponse[11];
    }

    /**
     * @return the dnsAnswer
     */
    public byte[] getDnsAnswer() {
        return dnsAnswer;
    }

    /**
     * @param dnsAnswer the dnsAnswer to set
     */
    public void setDnsAnswer(byte[] dnsAnswer) {
        this.dnsAnswer = dnsAnswer;
    }

    /**
     * @return the dnsFullResponse
     */
    public byte[] getDnsFullResponse() {
        return dnsFullResponse;
    }

    /**
     * @param dnsFullResponse the dnsFullResponse to set
     */
    public void setDnsFullResponse(byte[] dnsFullResponse) {
        this.dnsFullResponse = dnsFullResponse;
    }

    /**
     * @return the answerRecordCount
     */
    public int getAnswerRecordCount() {
        return answerRecordCount;
    }

    /**
     * @param answerRecordCount the answerRecordCount to set
     */
    public void setAnswerRecordCount(int answerRecordCount) {
        this.answerRecordCount = answerRecordCount;
    }

    /**
     * @return the nameServerCount
     */
    public int getNameServerCount() {
        return nameServerCount;
    }

    /**
     * @param nameServerCount the nameServerCount to set
     */
    public void setNameServerCount(int nameServerCount) {
        this.nameServerCount = nameServerCount;
    }

    /**
     * @return the additionRecordsCount
     */
    public int getAdditionRecordsCount() {
        return additionRecordsCount;
    }

    /**
     * @param additionRecordsCount the additionRecordsCount to set
     */
    public void setAdditionRecordsCount(int additionRecordsCount) {
        this.additionRecordsCount = additionRecordsCount;
    }
    DnsEntry parseEntry()
    {
        DnsEntry entry= new DnsEntry();
        if (getUnsignedByte(dnsFullResponse[offset])>191)
        {//is pointer
            String point= parsePointer(getUnsignedByte(dnsFullResponse[offset]),getUnsignedByte(dnsFullResponse[offset+1]));
            offset=offset +2 ;
            entry.setName("pointer + "+point);
            System.out.println("found pointer");

        }
        else
        {//not pointer
                        System.out.println("not found pointer");
        }
        entry.setType(extract2Bytes());
        entry.setClass_(extract2Bytes());
        entry.setTtl(extract4Bytes());
        entry.setLen(extract2Bytes());
        int[] content= new int[entry.getLen()+1];
        for (int i=0;i<entry.getLen();i++)
        {
           content[i] = getUnsignedByte( dnsFullResponse[offset] );
           System.out.println("*////*");
           if(i== entry.getLen()-2)
           {
               if (getUnsignedByte( dnsFullResponse[offset] )>191 &&( entry.getClass_() != 1 && entry.getType()!=1 ))
               {
                   parsePointer(getUnsignedByte( dnsFullResponse[offset] ), getUnsignedByte( dnsFullResponse[offset+1] ));
                   offset++;
                   i++;
               }
           }  
         offset ++ ;
        }
        entry.setContentInt(content);
        


        return entry;
    }
    public int extract2Bytes()
    {
        int ret;
        ret = getUnsignedByte(dnsFullResponse[offset])*256 + getUnsignedByte(dnsFullResponse[offset+1]);
        offset= offset +2 ;
        return ret;
    }
    public int extract4Bytes()
    {
        int ret;
        ret = getUnsignedByte(dnsFullResponse[offset])*256*256*256 + getUnsignedByte(dnsFullResponse[offset+1])*256*256+getUnsignedByte(dnsFullResponse[offset+2])*256 + getUnsignedByte(dnsFullResponse[offset+3]);
        offset= offset +4 ;
        return ret;
    }

    public int getUnsignedByte(byte b) {
        int val = b & 0x80;

        val += b & 0x7F;
        return val;
    }

    private int readUnsignedShort() {
    //read 2 bytes
        int ret =0;

        return ret;
        
        //     return ((getUnsignedByte(dnsFullResponse[offset++])-192) * 256) + getUnsignedByte(dnsFullResponse[offset++]);
    }

    private int readInt() {
        return (readUnsignedShort() << 16) + readUnsignedShort();
    }

    public String parseSection(int startIndex, int lenght) {
        String return_value = "";
        for (int i = startIndex; i < startIndex + lenght; i++) {
            return_value += "" + getUnsignedByte(dnsFullResponse[i]);
            if (getUnsignedByte(dnsFullResponse[i])== 0)
            {
                break;
            }
        }
        return return_value;
    }

    public String parsePointer(int byte0, int byte1) {
        int pointedLocation = (byte0 - 192) * 256 + byte1;
        String ret = "";
        int currentIndex = pointedLocation;
        int currentValue = getUnsignedByte(dnsFullResponse[currentIndex]);
        while (currentValue != 0) {
            ret += parseSection(currentIndex + 1, currentValue)+"||";
            currentIndex += currentValue+1;
            currentValue= getUnsignedByte(dnsFullResponse[currentIndex]);
            if(getUnsignedByte(dnsFullResponse[currentIndex+1])==0)
            {
                break;
            }
        }
        return  ret;
    }



    public void parse() {
       entryList= new ArrayList<DnsEntry>();
        int n = answerRecordCount + nameServerCount + additionRecordsCount;
        if (n > 0) {
            answers = new ArrayList(n);
            for (int i = 0; i < n; i++) {
              entryList.add(parseEntry());
            }
        }
    }
}

